﻿using System;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using System.Xml.Xsl;
using NuGet.Enterprise.Server;
using System.Collections.Generic;
using System.Xml;
using System.Web.Caching;
using NuGet.Enterprise.Server.Xml.Xsl;

namespace NuGet.Enterprise.Server.Web.Handlers
{
    public class RssHandler : IHttpHandler
    {
        #region Statics

        private static readonly XslCompiledTransform Stylesheet = CreateStylesheet("~/content/transform/rsstransform.xslt");

        private static XslCompiledTransform CreateStylesheet(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                url = HttpContext.Current.Server.MapPath("~/content/transform/copytransform.xslt");
            }
            else
            {
                url = HttpContext.Current.Server.MapPath(url);
            }

            var xslDoc = new XslCompiledTransform();

            xslDoc.Load(url);

            return xslDoc;
        }

        private static bool IsXmlHttpRequest(HttpRequest request)
        {
#if DEBUG
            return true;
#else
            var header = (from key in request.Headers.AllKeys
                          where key.Equals("X-Requested-With", StringComparison.OrdinalIgnoreCase)
                          select request.Headers[key]).FirstOrDefault();

            return string.Equals(header, "XMLHttpRequest", StringComparison.OrdinalIgnoreCase);
#endif
        }

        private static XmlReader GetFeed(string url)
        {

            var key = url.Trim().ToUpperInvariant();

            var rss = HttpRuntime.Cache.Get(key, delegate()
            {
#if DEBUG
                var expires = Cache.NoAbsoluteExpiration;
#else
                var expires = DateTime.Now.AddMinutes(5);
#endif

                HttpRuntime.Cache.Add(key, XDocument.Load(url), null,
                                      expires,
                                      Cache.NoSlidingExpiration,
                                      CacheItemPriority.Default, null);
            }) as XDocument;

            return (rss == null ? null : rss.CreateReader());
        }

        #endregion

        #region IHttpHandler Members

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            string feedUrl;

            if (IsXmlHttpRequest(context.Request) && context.Request.TryGetQueryStringValue<string>("feed", out feedUrl))
            {
                using (var feed = GetFeed(feedUrl))
                {
                    var args = new XsltArgumentList();

                    args.AddExtensionObject("urn:Extensions", new XsltExtensions());

                    string styleUrl;

                    if (context.Request.TryGetQueryStringValue<string>("style", out styleUrl))
                    {
                        var stylesheet = CreateStylesheet(styleUrl);

                        stylesheet.Transform(feed, args, context.Response.Output);
                    }
                    else
                    {
                        Stylesheet.Transform(feed, args, context.Response.Output);
                    }
                }
            }
            else
            {
                context.Response.StatusCode = 404;
                context.Response.End();
            }
        }

        #endregion
    }
}
